package org.example.domain.strategy.service.armory;

import org.example.domain.strategy.model.entity.StrategyAwardEntity;
import org.example.domain.strategy.model.entity.StrategyRuleEntity;
import org.example.domain.strategy.repository.IStrategyRepository;
import org.example.domain.strategy.repository.IStrategyRuleRepository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.*;

@Service
public class StrategyArmoryDispatch implements IStrategyArmory, IStrategyDispatch{
    @Resource
    private IStrategyRepository strategyRepository;
    @Resource
    private IStrategyRuleRepository strategyRuleRepository;
    @Override
    public boolean assembleLotteryStrategy(Long strategyId) {
        /* 查询是否以及装配策略 */
        if(strategyRepository.queryIfExistStrategyAwardSearchRateMap(strategyId)) return true;
        List<StrategyAwardEntity> strategyAwardEntityList = strategyRepository.queryStrategyAwardList(strategyId);
        assembleLotteryStrategy(strategyId.toString(), strategyAwardEntityList);

        /* 查询装配策略权重rule_weight规则 */
        List<StrategyRuleEntity> strategyRuleEntityList = strategyRuleRepository.queryStrategyRuleEntityByStrategyId(strategyId);
        if (strategyRuleEntityList.isEmpty()) {
            return true;
        }
        Map<Long, List<Long>> ruleWeightMap = StrategyRuleEntity.getRuleWeightValueFromList(strategyRuleEntityList);
        for (Long group : ruleWeightMap.keySet()) {
            List<Long> weightList = ruleWeightMap.get(group);
            List<StrategyAwardEntity> strategyAwardEntityListForWeight = new ArrayList<>(strategyAwardEntityList);
            strategyAwardEntityListForWeight.removeIf(award -> !weightList.contains(award.getAwardId()));
            assembleLotteryStrategy(String.valueOf(strategyId).concat("_").concat(group.toString()), strategyAwardEntityListForWeight);
        }
        return true;
    }

    public void assembleLotteryStrategy(String key, List<StrategyAwardEntity> strategyAwardEntityList) {
        int maxCount = strategyAwardEntityList.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .max(new Comparator<BigDecimal>() {
                    @Override
                    public int compare(BigDecimal o1, BigDecimal o2) {
                        return o1.scale() - o2.scale();
                    }
                })
                .orElse(BigDecimal.ZERO)
                .scale();
        int multiElement = (int)Math.pow(10, maxCount);

        ArrayList<Long> lotteryList = new ArrayList<>();
        for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntityList) {
            Long value = strategyAwardEntity.getAwardId();
            for (int i = 0; i < strategyAwardEntity.getAwardRate().multiply(new BigDecimal(multiElement)).intValue(); i++) {
                lotteryList.add(value);
            }
        }
        Collections.shuffle(lotteryList);
        Map<Integer, Long> lotteryMap = new HashMap<>();
        for (int i = 0; i < lotteryList.size(); i++) {
            lotteryMap.put(i, lotteryList.get(i));
        }
        strategyRepository.storeStrategyRateMapAndRange(key, lotteryMap, lotteryList.size());
    }


    @Override
    public Long getRandomStrategyAwardId(Long strategyId) {
        Integer range = strategyRepository.getRateRange(strategyId);
        return strategyRepository.getStrategyAwardIdFromMap(strategyId, new SecureRandom().nextInt(range));
    }

    @Override
    public Long getRandomStrategyAwardId(Long strategyId, String group) {
        String key = String.valueOf(strategyId).concat("_").concat(group);
        Integer range = strategyRepository.getRateRange(key);
        return strategyRepository.getStrategyAwardIdFromMap(key, new SecureRandom().nextInt(range));
    }
}
